﻿using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Events.Bus.Handlers;
using Abp.ObjectMapping;
using ARchGL.Platform.Application;
using ARchGL.Platform.Core;
using ARchGL.Platform.EventHandlers.Events;
using Castle.Core.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ARchGL.Platform.Qianbian.EventHandlers
{
    /// <summary>
    /// 千变数据同步 Handler
    /// </summary>
    public class QianbianSyncEventHandler : IAsyncEventHandler<QianbianSyncEvent>, ITransientDependency
    {
        #region 定义
        private readonly IQianbianAppService qianBianAppService;
        private readonly IRepository<Machines, Guid> machinesRepository;
        private readonly IRepository<QB_Projects, Guid> qb_projectRepository;
        private readonly IRepository<QB_ProjectUsers, Guid> qb_projectUsersRepository;
        private readonly IRepository<QB_ProjectVideos, Guid> qb_projectVideosRepository;
        private readonly IRepository<QB_ProjectAttendances, Guid> qb_projectAttendancesRepository;
        private readonly IRepository<QB_ProjectDevices, Guid> qb_projectDevicesRepository;
        private readonly IRepository<QB_ProjectCranes, Guid> qb_projectCranesRepository;
        private readonly IRepository<QB_ProjectLifts, Guid> qb_projectLiftsRepository;
        private readonly IRepository<QB_ProjectEnvironments, Guid> qb_projectEnvironmentsRepository;
        private readonly IRepository<QB_ProjectVideoPlays, Guid> qb_projectVideoPlaysRepository;
        private readonly IRepository<QB_EventJobs, Guid> qb_eventJobsRepository;
        private readonly IObjectMapper objectMapper;
        private readonly ILogger _logger;

        private const int _EventKeyIdNumber = 2; //计数器 区分数据平台源个数
        private const int _CurrentPage = 0; //页码

        private const int _LimitPassDays = 10; //向前推算多少天

        public List<QB_ProjectEnvironments> AllEnvData = new List<QB_ProjectEnvironments>(); //所有环境数据
        public List<QB_ProjectAttendances> AllAttrData = new List<QB_ProjectAttendances>(); //所有空勤数据
        public List<QB_ProjectLifts> AllLiftData = new List<QB_ProjectLifts>(); //所有升降机数据
        public List<QB_ProjectCranes> allCranesData = new List<QB_ProjectCranes>(); //所有塔吊监测数据

        public QianbianSyncEventHandler(
            IQianbianAppService _qianBianAppService,
            IRepository<Machines, Guid> _machinesRepository,
            IRepository<QB_Projects, Guid> _qb_projectRepository,
            IRepository<QB_ProjectUsers, Guid> _qb_projectUsersRepository,
            IRepository<QB_ProjectVideos, Guid> _qb_projectVideosRepository,
            IRepository<QB_ProjectAttendances, Guid> _qb_projectAttendancesRepository,
            IRepository<QB_ProjectDevices, Guid> _qb_projectDevicesRepository,
            IRepository<QB_ProjectCranes, Guid> _qb_projectCranesRepository,
            IRepository<QB_ProjectLifts, Guid> _qb_projectLiftsRepository,
            IRepository<QB_ProjectEnvironments, Guid> _qb_projectEnvironmentsRepository,
            IRepository<QB_ProjectVideoPlays, Guid> _qb_projectVideoPlaysRepository,
            IRepository<QB_EventJobs, Guid> _qb_eventJobsRepository,
            IObjectMapper _objectMapper)
        {
            qianBianAppService = _qianBianAppService;
            machinesRepository = _machinesRepository;
            qb_projectRepository = _qb_projectRepository;
            qb_projectUsersRepository = _qb_projectUsersRepository;
            qb_projectVideosRepository = _qb_projectVideosRepository;
            qb_projectAttendancesRepository = _qb_projectAttendancesRepository;
            qb_projectDevicesRepository = _qb_projectDevicesRepository;
            qb_projectCranesRepository = _qb_projectCranesRepository;
            qb_projectLiftsRepository = _qb_projectLiftsRepository;
            qb_projectEnvironmentsRepository = _qb_projectEnvironmentsRepository;
            qb_projectVideoPlaysRepository = _qb_projectVideoPlaysRepository;
            qb_eventJobsRepository = _qb_eventJobsRepository;
            objectMapper = _objectMapper;
        }
        #endregion

        [UnitOfWork]
        public async Task HandleEventAsync(QianbianSyncEvent e)
        {
            QB_EnumEventArg enumEvent = e.Code;
            if (enumEvent == QB_EnumEventArg.项目)
            {
                int cntProj = 1;
                while (cntProj <= _EventKeyIdNumber)
                {
                    await SyncProjectPagedList(_CurrentPage, cntProj++);
                }
            }
            else if (enumEvent == QB_EnumEventArg.考勤)
            {
                //同步考勤
                await HandleAttendancesAsync();
            }
            else if (enumEvent == QB_EnumEventArg.设备)
            {
                //同步设备读数
                await HandleDevicesAsync();
            }
            else if (enumEvent == QB_EnumEventArg.环境)
            {
                //同步环境读数
                await HandleEnvironmentsAsync();
            }
            else
            {
                //重新同步项目数据
                if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday && DateTime.Now.Hour == 1)
                {
                    //每周星期天凌晨1点尝试清理一次数据，并重新同步
                    await qianBianAppService.Async2();
                }
                else
                {
                    //Thread.Sleep(10000);
                    await SyncProjectPagedList(_CurrentPage, _EventKeyIdNumber);
                    await HandleAttendancesAsync();
                    await HandleDevicesAsync();
                    await HandleEnvironmentsAsync();
                }
            }
        }

        #region 事件

        /// <summary>
        /// 考勤
        /// </summary>
        /// <returns></returns>
        private async Task HandleAttendancesAsync()
        {
            int _dspan = 1;
            AllAttrData = await qb_projectAttendancesRepository.GetAllListAsync();
            var projectList = await qb_projectRepository.GetAllListAsync();
            var now = DateTime.Now.Date;
            var start = DateTime.Now.AddDays(-_LimitPassDays).Date;
            try
            {
                //获取任务开始执行日期
                start = qb_eventJobsRepository.GetQB_EventDate(QB_EnumEventArg.考勤, start);
            }
            catch (Exception ex)
            {
                Console.WriteLine("[GetQB_EventDate异常]" + ex.Message);
            }
            //Console.WriteLine("HandleAttendancesAsync" + date.ToString("yyyy-MM-dd"));
            bool finish = false;

            if (projectList.Any())
            {
                for (int pindex = 0; pindex < projectList.Count; pindex++)
                {
                    for (int i = 1; i <= _EventKeyIdNumber; i++)
                    {
                        DateTime date = start;
                        //DateTime date = limitDate; //DateTime.Now.Date;
                        while (date < now.AddDays(1).Date)
                        {
                            await SyncProjectAttendancesPagedListByProjectId(0, i, projectList[pindex].Id, date);
                            date = date.AddDays(_dspan);
                        }
                    }
                    finish = pindex == projectList.Count - 1;
                }
            }

            try
            {
                if (finish)
                {
                    //执行完成更新时间日期为最新
                    qb_eventJobsRepository.UpdQB_EventDate(QB_EnumEventArg.考勤, now.Date);
                }
            }
            catch
            {
            }
        }

        /// <summary>
        /// 设备监测
        /// </summary>
        /// <returns></returns>
        private async Task HandleDevicesAsync()
        {
            AllLiftData = await qb_projectLiftsRepository.GetAllListAsync();
            if (AllLiftData == null) AllLiftData = new List<QB_ProjectLifts>();
            allCranesData = await qb_projectCranesRepository.GetAllListAsync();
            if (allCranesData == null) allCranesData = new List<QB_ProjectCranes>();

            //获取设备
            var _dspan = -1;
            var limitDate = DateTime.Now.AddDays(-_LimitPassDays).Date;
            var devList = await qb_projectDevicesRepository.GetAllListAsync();
            if (devList.Any())
            {
                for (int i = 0; i < devList.Count; i++)
                {
                    var dev = devList[i];
                    //st1.5.1 同步项目塔吊监测数据
                    int cntCranes = 1;
                    while (cntCranes <= _EventKeyIdNumber)
                    {
                        DateTime end = DateTime.Now.AddDays(1).Date;
                        DateTime start = end.AddDays(_dspan);
                        while (end >= limitDate)
                        {
                            await SyncProjectCranesPagedListByProjectId(0, cntCranes, start, end, dev.ProjectId, dev.SN);
                            end = end.AddDays(_dspan);
                            start = start.AddDays(_dspan);
                        }
                        cntCranes++;
                    }

                    //st1.5.2 同步项目升降机监测数据
                    int cntLift = 1;
                    while (cntLift <= _EventKeyIdNumber)
                    {
                        DateTime end = DateTime.Now.AddDays(1).Date;
                        DateTime start = end.AddDays(_dspan);
                        while (end >= limitDate)
                        {
                            await SyncProjectLiftsPagedListByProjectId(0, cntLift, start, end, dev.ProjectId, dev.SN);
                            end = end.AddDays(_dspan);
                            start = start.AddDays(_dspan);
                        }
                        cntLift++;
                    }
                }
            }
        }

        /// <summary>
        /// 环境
        /// </summary>
        /// <returns></returns>
        private async Task HandleEnvironmentsAsync()
        {
            //获取环境表数据
            AllEnvData = await qb_projectEnvironmentsRepository.GetAllListAsync();
            if (AllEnvData == null) AllEnvData = new List<QB_ProjectEnvironments>();
            //获取设备
            int _dspan = -1;
            var limitDate = DateTime.Now.AddDays(-_LimitPassDays).Date;
            var devList = await qb_projectDevicesRepository.GetAllListAsync();
            if (devList.Any())
            {
                for (int i = 0; i < devList.Count; i++)
                {
                    var dev = devList[i];
                    //st1.5.3 同步环境监测数据
                    int cntEnv = 1;
                    while (cntEnv <= _EventKeyIdNumber)
                    {
                        DateTime start = DateTime.Now.AddDays(_dspan).Date;
                        DateTime end = DateTime.Now.AddDays(1).Date;
                        while (end >= limitDate)
                        {
                            await SyncProjectEnvironmentsPagedListByProjectId(0, cntEnv, start, end, dev.ProjectId, dev.SN);
                            end = end.AddDays(_dspan);
                            start = start.AddDays(_dspan);
                        }
                        cntEnv++;
                    }
                }
            }
        }

        #endregion

        #region 业务

        /// <summary>同步项目信息</summary>
        public async Task SyncProjectPagedList(int page, int count)
        {
            try
            {
                var result = await qianBianAppService.GetProjectPagedList(page, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_Projects>>(items);

                    //写入获取到的数据集

                    for (int i = 0; i < list.Count; i++)
                    {
                        var t = list[i];
                        if (await qb_projectRepository.CountAsync(x => x.Id == t.Id) <= 0)
                        {
                            t.TenantId = 1;
                            await qb_projectRepository.InsertAsync(t);
                        }
                        //st1.2 同步项目成员数据
                        await SyncProjectUserPagedListByProjectId(0, count, t.Id);

                        //st1.3 同步项目视频数据
                        await SyncProjectVideoPagedListByProjectId(count, t.Id);

                        //st1.4 同步考勤数据
                        //await SyncProjectAttendancesPagedListByProjectId(0, count, t.Id, DateTime.Now);

                        //st1.5 同步项目设备信息
                        await SyncProjectDevicesPagedListByProjectId(0, count, t.Id);
                    }
                }
                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    int newpage = page + 1; //下一页
                    await SyncProjectPagedList(newpage, count);
                }
            }
            catch (Exception)
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步项目成员信息</summary>
        public async Task SyncProjectUserPagedListByProjectId(int page, int count, Guid projectId)
        {
            try
            {
                var result = await qianBianAppService.GetProjectUserPagedList(page, projectId, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectUsers>>(items);

                    if (await qb_projectUsersRepository.CountAsync(x => list.Any(a => a.UserId == x.UserId) && x.ProjectId == projectId) <= 0)
                    {
                        //写入获取到的数据集
                        for (int i = 0; i < list.Count; i++)
                        {
                            var t = list[i];

                            t.TenantId = 1;
                            t.Id = Guid.NewGuid();
                            t.ProjectId = projectId;
                            await qb_projectUsersRepository.InsertAsync(t);
                        }
                    }
                }
                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    page++; //下一页
                    await SyncProjectUserPagedListByProjectId(page, count, projectId);
                }
            }
            catch
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步项目视频信息</summary>
        public async Task SyncProjectVideoPagedListByProjectId(int count, Guid projectId)
        {
            try
            {
                var result = await qianBianAppService.GetProjectsVideoList(projectId, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectVideos>>(items);
                    var blackBoxIdList = list.Select(x => x.Id.ToString()).ToList(); //把视频的 id 当作黑匣子标识
                    var machinesList = await machinesRepository.GetAllListAsync(x => blackBoxIdList.Contains(x.BlackBoxId)); //设备信息
                    var videoList = await qb_projectVideosRepository.GetAllListAsync(x => x.ProjectId == projectId); //视频

                    //写入获取到的数据集
                    for (int i = 0; i < list.Count; i++)
                    {
                        var item = list[i];

                        item.TenantId = 1;
                        item.ProjectId = projectId;

                        var playsResult = await qianBianAppService.GetProjectsVideoPlay(projectId, item.Id, count);
                        var play = objectMapper.Map<QB_ProjectVideoPlays>(playsResult.Items);
                        if (play != null) item.PlayUrl = play.PlayUrl;

                        if (!machinesList.Any(x => x.BlackBoxId == item.Id.ToString()))
                            await machinesRepository.InsertAsync(new Machines(item.Id.ToString(), item.Number, 1, 3));

                        if (!videoList.Any(x => x.Id == item.Id))
                            await qb_projectVideosRepository.InsertAsync(item);
                    }
                }
            }
            catch (Exception)
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步项目视频地址信息</summary>
        public async Task SyncProjectVideoPlayByProjectId(int count, Guid videoId, Guid projectId)
        {
            try
            {
                if (await qb_projectVideoPlaysRepository.CountAsync(x => x.Id == videoId) <= 0)
                {
                    var result = await qianBianAppService.GetProjectsVideoPlay(projectId, videoId, count);

                    if (result.Items != null)
                    {
                        var obj = objectMapper.Map<QB_ProjectVideoPlays>(result.Items);

                        //写入获取到的数据集
                        if (obj != null)
                        {
                            obj.TenantId = 1;
                            obj.Id = videoId;
                            obj.ProjectId = projectId;
                            await qb_projectVideoPlaysRepository.InsertAsync(obj);
                        }
                    }
                }
            }
            catch (Exception)
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步项目考勤信息</summary>
        public async Task SyncProjectAttendancesPagedListByProjectId(int page, int count, Guid projectId, DateTime date)
        {
            try
            {
                if (page > 10) return;

                var result = await qianBianAppService.GetProjectAttendancePagedList(date.ToString("yyyy-MM-dd"), page, projectId, count);
                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectAttendances>>(items);

                    //写入获取到的数据集
                    foreach (var item in list)
                    {
                        try
                        {
                            if (!AllAttrData.Any(x => x.IdCardSHA == item.IdCardSHA && x.ProjectId == projectId && x.AttendanceTime == item.AttendanceTime))
                            {
                                //if (await qb_projectAttendancesRepository.CountAsync(x => x.IdCardSHA == item.IdCardSHA && x.ProjectId == projectId && x.AttendanceTime == item.AttendanceTime) <= 0)
                                //{
                                item.TenantId = 1;
                                item.ProjectId = projectId;
                                item.Id = Guid.NewGuid();
                                var entity = await qb_projectAttendancesRepository.InsertAsync(item);
                                AllAttrData.Add(entity);
                            }
                        }
                        catch
                        {
                            continue;
                        }
                    }
                }
                if (result.TotalPage.HasValue && page < 10 && page < result.TotalPage)
                {
                    int pagenew = page + 1; //下一页
                    await SyncProjectAttendancesPagedListByProjectId(pagenew, count, projectId, date);
                }
            }
            catch (Exception ex)
            {
                string error = $"考勤qianBianAppService.GetProjectAttendancePagedList({date.ToString("yyyy - MM - dd")}, {page}, {projectId}, {count})";
                Console.WriteLine($"[考勤error]{error}====[ex]" + ex.Message);
                //记录日志
                //throw;
            }
        }

        /// <summary>同步项目设备信息</summary>
        public async Task SyncProjectDevicesPagedListByProjectId(int page, int count, Guid projectId)
        {
            try
            {
                var result = await qianBianAppService.GetProjectDevicePagedList(page, projectId, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectDevices>>(items);

                    //写入获取到的数据集
                    for (int i = 0; i < list.Count; i++)
                    {
                        var t = list[i];
                        if (await qb_projectDevicesRepository.CountAsync(x => x.Id == t.Id) <= 0)
                        {
                            t.TenantId = 1;
                            t.ProjectId = projectId;
                            await qb_projectDevicesRepository.InsertAsync(t);
                        }
                    }
                }

                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    page++; //下一页
                    await SyncProjectDevicesPagedListByProjectId(page, count, projectId);
                }
            }
            catch (Exception)
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步塔吊检测数据</summary>
        public async Task SyncProjectCranesPagedListByProjectId(int page, int count, DateTime start, DateTime end, Guid projectId, string serialNumber)
        {
            try
            {
                var result = await qianBianAppService.GetProjectsCranePagedList(start, end, page, projectId, serialNumber, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectCranes>>(items);

                    //写入获取到的数据集
                    for (int i = 0; i < list.Count; i++)
                    {
                        var t = list[i];
                        if (!allCranesData.Any(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime))
                        {
                            //if (await qb_projectCranesRepository.CountAsync(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime) <= 0)
                            //{
                            t.TenantId = 1;
                            t.ProjectId = projectId;
                            t.SerialNumber = serialNumber;
                            t.Id = Guid.NewGuid();
                            var entity = await qb_projectCranesRepository.InsertAsync(t);
                            allCranesData.Add(entity);
                        }
                    }
                }

                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    int pagenew = page + 1; //下一页
                    await SyncProjectCranesPagedListByProjectId(pagenew, count, start, end, projectId, serialNumber);
                }
            }
            catch
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步升降机检测数据</summary>
        public async Task SyncProjectLiftsPagedListByProjectId(int page, int count, DateTime start, DateTime end, Guid projectId, string serialNumber)
        {
            try
            {
                var result = await qianBianAppService.GetProjectsLiftPagedList(start, end, page, projectId, serialNumber, count);

                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectLifts>>(items);

                    //写入获取到的数据集
                    for (int i = 0; i < list.Count; i++)
                    {
                        var t = list[i];
                        if (!AllLiftData.Any(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime))
                        {
                            //if (await qb_projectLiftsRepository.CountAsync(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime) <= 0)
                            //{
                            t.TenantId = 1;
                            t.ProjectId = projectId;
                            t.SerialNumber = serialNumber;
                            t.Id = Guid.NewGuid();
                            var entity = await qb_projectLiftsRepository.InsertAsync(t);
                            AllLiftData.Add(entity);
                        }
                    }
                }

                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    int pagenew = page + 1; //下一页
                    await SyncProjectLiftsPagedListByProjectId(pagenew, count, start, end, projectId, serialNumber);
                }
            }
            catch (Exception)
            {
                //记录日志
                //throw;
            }
        }

        /// <summary>同步环境检测数据</summary>
        public async Task SyncProjectEnvironmentsPagedListByProjectId(int page, int count, DateTime start, DateTime end, Guid projectId, string serialNumber)
        {
            try
            {
                var result = await qianBianAppService.GetProjectsEnvironmentPagedList(start, end, page, projectId, serialNumber, count);
                var items = result.Items;
                if (items?.Count > 0)
                {
                    var list = objectMapper.Map<List<QB_ProjectEnvironments>>(items);
                    for (int i = 0; i < list.Count; i++) //写入获取到的数据集
                    {
                        var t = list[i];
                        if (!AllEnvData.Any(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime))
                        {
                            //if (await qb_projectEnvironmentsRepository.CountAsync(x => x.ProjectId == projectId && x.SerialNumber == serialNumber && x.RecordTime == t.RecordTime) <= 0)
                            //{
                            t.TenantId = 1;
                            t.ProjectId = projectId;
                            t.SerialNumber = serialNumber;
                            t.Id = Guid.NewGuid();
                            var entity = await qb_projectEnvironmentsRepository.InsertAsync(t);
                            AllEnvData.Add(entity);
                        }
                    }
                }
                if (result.TotalPage.HasValue && page < result.TotalPage)
                {
                    int pagenew = page + 1; //下一页
                    await SyncProjectEnvironmentsPagedListByProjectId(pagenew, count, start, end, projectId, serialNumber);
                }
            }
            catch
            {
                //记录日志
                //throw;
            }
        }

        #endregion
    }
}
